import os
import struct
from typing import List, Dict, Any, Optional
from .catalog_manager import TableInfo, ColumnInfo

class StorageEngine:
    def __init__(self, data_dir: str = "data"):
        self.data_dir = data_dir
        self._ensure_data_dir()
    
    def _ensure_data_dir(self):
        """确保数据目录存在"""
        if not os.path.exists(self.data_dir):
            os.makedirs(self.data_dir)
    
    def _get_table_file(self, table_name: str) -> str:
        """获取表数据文件路径"""
        return os.path.join(self.data_dir, f"{table_name}.dat")
    
    def _serialize_record(self, table_info: TableInfo, record: Dict[str, Any]) -> bytes:
        """序列化记录为字节"""
        data = bytearray()
        
        for column in table_info.columns:
            value = record.get(column.name)
            
            if value is None:
                # 空值标记
                data.append(0)
                continue
            
            data.append(1)  # 非空标记
            
            if column.type == "INT":
                # 4字节整数
                data.extend(struct.pack('i', value))
            elif column.type == "VARCHAR":
                # 变长字符串，先写入长度，再写入内容
                str_bytes = value.encode('utf-8')
                data.extend(struct.pack('i', len(str_bytes)))
                data.extend(str_bytes)
        
        return bytes(data)
    
    def _deserialize_record(self, table_info: TableInfo, data: bytes) -> Dict[str, Any]:
        """从字节反序列化记录"""
        record = {}
        pos = 0
        
        for column in table_info.columns:
            # 读取空值标记
            is_null = data[pos] == 0
            pos += 1
            
            if is_null:
                record[column.name] = None
                continue
            
            if column.type == "INT":
                # 读取4字节整数
                value = struct.unpack('i', data[pos:pos+4])[0]
                pos += 4
                record[column.name] = value
            elif column.type == "VARCHAR":
                # 读取字符串长度和内容
                length = struct.unpack('i', data[pos:pos+4])[0]
                pos += 4
                value = data[pos:pos+length].decode('utf-8')
                pos += length
                record[column.name] = value
        
        return record
    
    def insert_record(self, table_info: TableInfo, record: Dict[str, Any]) -> bool:
        """插入记录"""
        table_file = self._get_table_file(table_info.name)
        serialized = self._serialize_record(table_info, record)
        
        with open(table_file, 'ab') as f:
            # 写入记录长度和记录内容
            f.write(struct.pack('i', len(serialized)))
            f.write(serialized)
        
        return True
    
    def get_all_records(self, table_info: TableInfo) -> List[Dict[str, Any]]:
        """获取所有记录"""
        table_file = self._get_table_file(table_info.name)
        records = []
        
        if not os.path.exists(table_file):
            return records
        
        with open(table_file, 'rb') as f:
            while True:
                # 读取记录长度
                len_bytes = f.read(4)
                if not len_bytes:
                    break
                
                record_len = struct.unpack('i', len_bytes)[0]
                # 读取记录内容
                record_data = f.read(record_len)
                
                if len(record_data) < record_len:
                    break  # 文件损坏或不完整
                
                record = self._deserialize_record(table_info, record_data)
                records.append(record)
        
        return records
    
    def delete_records(self, table_info: TableInfo, condition_func) -> int:
        """删除满足条件的记录，返回删除的记录数"""
        table_file = self._get_table_file(table_info.name)
        temp_file = table_file + ".tmp"
        deleted_count = 0
        
        if not os.path.exists(table_file):
            return 0
        
        with open(table_file, 'rb') as f_in, open(temp_file, 'wb') as f_out:
            while True:
                # 读取记录长度
                len_bytes = f_in.read(4)
                if not len_bytes:
                    break
                
                record_len = struct.unpack('i', len_bytes)[0]
                pos = f_in.tell()
                # 读取记录内容
                record_data = f_in.read(record_len)
                
                if len(record_data) < record_len:
                    break  # 文件损坏或不完整
                
                record = self._deserialize_record(table_info, record_data)
                
                # 检查是否满足删除条件
                if condition_func(record):
                    deleted_count += 1
                else:
                    # 保留记录
                    f_out.write(len_bytes)
                    f_out.write(record_data)
        
        # 替换原文件
        if os.path.exists(temp_file):
            os.replace(temp_file, table_file)
        
        return deleted_count